home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Workbench Add-On
/
Workbench Add-On - Volume 1.iso
/
BBS-Archive
/
Dev
/
GNU-SMALLTALK.lha
/
mst.y
< prev
next >
Wrap
Text File
|
1992-02-15
|
10KB
|
443 lines
/* -*- bison -*- */
/***********************************************************************
*
* Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
* Written by Steve Byrne.
*
* This file is part of GNU Smalltalk.
*
* GNU Smalltalk is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 1, or (at your option) any later
* version.
*
* GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* GNU Smalltalk; see the file COPYING. If not, write to the Free Software
* Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
***********************************************************************/
%{
#include "mst.h"
#include "mstsym.h"
#include "msttree.h"
#include "mstdict.h"
#include "mstcomp.h"
#include <stdio.h>
#ifdef HAS_ALLOCA_H
#include <alloca.h>
#endif
#define YYDEBUG 1
extern Boolean quietExecution;
%}
%pure_parser
%union{
char cval;
double fval;
long ival;
char *sval;
TreeNode node;
}
/* single definite characters */
%token BANG COLON UPARROW DOT ASSIGN SHARP SEMICOLON
%token OPEN_PAREN CLOSE_PAREN OPEN_BRACKET CLOSE_BRACKET
%token PRIMITIVE_START INTERNAL_TOKEN
/* larger lexical items */
%token <sval> IDENTIFIER KEYWORD STRING_LITERAL SYMBOL_KEYWORD BINOP
VERTICAL_BAR
%token <ival> INTEGER_LITERAL
%token <fval> FLOATING_LITERAL
%token <cval> CHAR_LITERAL
%type <node> method message_pattern variable_name keyword_variable_list
temporaries variable_names statements non_empty_statements expression
assigns primary number symbol_constant symbol
character_constant string array_constant array
array_constant_list block opt_block_variables
block_variable_list unary_expression binary_expression
keyword_expression keyword_binary_object_description_list
cascaded_message_expression semi_message_list
message_elt simple_expression literal message_expression
array_constant_elt unary_object_description
binary_object_description
%type <sval> unary_selector keyword binary_selector
%type <ival> primitive
%%
program:
class_definition_list
| internal_marker method { compileMethod($2); }
| /* EMPTY */
;
internal_marker:
INTERNAL_TOKEN { clearMethodStartPos(); }
class_definition_list:
class_definition
| class_definition_list class_definition
;
class_definition:
class_header method_list BANG { skipCompilation = false; }
| class_header BANG { skipCompilation = false; }
| non_empty_statements BANG { if (!hadError) {
executeStatements(nil, $1,
quietExecution);
}
hadError = false;
}
| temporaries non_empty_statements BANG
{ if (!hadError) {
executeStatements($1, $2,
quietExecution);
}
hadError = false;
}
| error BANG { hadError = false;
yyerrok; }
;
class_header:
BANG class_specification BANG { clearMethodStartPos(); }
;
class_specification:
simple_expression { executeStatements(nil,
makeStatementList($1, nil), true); }
;
/*
method_list:
method { if (!hadError) {
if (skipCompilation) {
freeTree($1);
} else {
compileMethod($1);
}
} else {
hadError = false;
}
}
| method_list method { if (!hadError) {
if (skipCompilation) {
freeTree($2);
} else {
compileMethod($2);
}
} else {
hadError = false;
}
}
;
method:
message_pattern statements BANG
{ $$ = makeMethod($1, nil, 0, $2); }
| message_pattern temporaries statements BANG
{ $$ = makeMethod($1, $2, 0, $3); }
| message_pattern primitive statements BANG
{ $$ = makeMethod($1, nil, $2, $3); }
| message_pattern temporaries primitive statements BANG
{ $$ = makeMethod($1, $2, $3, $4); }
;
*/
method_list:
method BANG { if (!hadError) {
if (skipCompilation) {
freeTree($1);
} else {
compileMethod($1);
clearMethodStartPos();
}
} else {
hadError = false;
}
}
| method_list method BANG { if (!hadError) {
if (skipCompilation) {
freeTree($2);
} else {
compileMethod($2);
clearMethodStartPos();
}
} else {
hadError = false;
}
}
;
method:
message_pattern statements
{ $$ = makeMethod($1, nil, 0, $2); }
| message_pattern temporaries statements
{ $$ = makeMethod($1, $2, 0, $3); }
| message_pattern primitive statements
{ $$ = makeMethod($1, nil, $2, $3); }
| message_pattern temporaries primitive statements
{ $$ = makeMethod($1, $2, $3, $4); }
;
message_pattern:
unary_selector { $$ = makeUnaryExpr(nil, $1); }
| binary_selector variable_name { $$ = makeBinaryExpr(nil, $1,
$2); }
| keyword_variable_list { $$ = makeKeywordExpr(nil, $1); }
| error { errorf("Invalid message pattern");
hadError = true;
yyerrok;
$$ = nil; }
;
unary_selector:
IDENTIFIER
;
binary_selector:
BINOP /* I don't like this usage of binop */
| VERTICAL_BAR
;
variable_name:
IDENTIFIER { $$ = makeVariable($1); }
;
keyword_variable_list:
keyword variable_name { $$ = makeKeywordList($1, $2); }
| keyword_variable_list keyword variable_name
{ addNode($1, makeKeywordList($2, $3));
$$ = $1; }
;
keyword:
KEYWORD
;
primitive:
PRIMITIVE_START INTEGER_LITERAL BINOP
{ $$ = $2;
if (strcmp($3, ">") != 0) {
YYERROR;
}
}
temporaries:
VERTICAL_BAR VERTICAL_BAR { $$ = nil; }
| VERTICAL_BAR variable_names VERTICAL_BAR
{ $$ = $2; }
;
variable_names:
variable_name { $$ = makeVariableList($1); }
| variable_names variable_name { addNode($1, makeVariableList($2));
$$ = $1; }
;
statements:
/* empty */ { $$ = nil; }
| non_empty_statements
;
non_empty_statements:
UPARROW expression optional_dot
{ $$ = makeStatementList(makeReturn($2),
nil); }
| expression { $$ = makeStatementList($1, nil); }
| expression DOT statements
/* I don't know if I like this production */
{ $$ = makeStatementList($1, $3); }
| error DOT statements { $$ = $3;
yyerrok;
errorf("Error in expression");
hadError = true;
}
;
optional_dot:
/* empty */
| DOT
;
expression:
simple_expression
| assigns simple_expression { $$ = makeAssign($1, $2); }
;
assigns:
variable_name ASSIGN { $$ = makeVariableList($1); }
| assigns variable_name ASSIGN
{ addNode($1, makeVariableList($2));
$$ = $1; }
;
simple_expression:
primary
| message_expression
| cascaded_message_expression
;
primary:
variable_name
| literal
| block
| OPEN_PAREN expression CLOSE_PAREN { $$ = $2; }
;
literal:
number
| symbol_constant
| character_constant
| string
| array_constant
;
number:
INTEGER_LITERAL { $$ = makeIntConstant($1); }
| FLOATING_LITERAL { $$ = makeFloatConstant($1); }
;
symbol_constant:
SHARP symbol { $$ = makeSymbolConstant($2); }
;
symbol:
IDENTIFIER { $$ = internIdent($1); }
| binary_selector { $$ = internBinOP($1); }
| SYMBOL_KEYWORD { $$ = internIdent($1); }
| KEYWORD { $$ = internIdent($1); }
;
character_constant:
CHAR_LITERAL { $$ = makeCharConstant($1); }
;
string:
STRING_LITERAL { $$ = makeStringConstant($1); }
;
array_constant:
SHARP array { $$ = makeArrayConstant($2); }
;
array:
OPEN_PAREN CLOSE_PAREN { $$ = nil; }
| OPEN_PAREN array_constant_list CLOSE_PAREN
{ $$ = $2; }
;
array_constant_list:
array_constant_elt { $$ = makeArrayElt($1); }
| array_constant_list array_constant_elt
{ addNode($1, makeArrayElt($2));
$$ = $1; }
;
array_constant_elt:
number
| symbol
| string
| character_constant
| array
;
block:
OPEN_BRACKET opt_block_variables statements CLOSE_BRACKET
{ $$ = makeBlock($2, $3); }
;
opt_block_variables:
/* empty */ { $$ = nil; }
| block_variable_list VERTICAL_BAR
;
/* syntax for blocks with temporaries is just args and vertical bar (if
* any followed by a standard temporaries declarations */
block_variable_list:
COLON variable_name { $$ = makeVariableList($2); }
| block_variable_list COLON variable_name
{ addNode($1, makeVariableList($3));
$$ = $1; }
;
message_expression:
unary_expression
| binary_expression
| keyword_expression
;
unary_expression:
unary_object_description unary_selector { $$ = makeUnaryExpr($1, $2); }
;
unary_object_description:
primary
| unary_expression
;
binary_expression:
binary_object_description binary_selector unary_object_description
{ $$ = makeBinaryExpr($1, $2, $3); }
;
binary_object_description:
unary_object_description
| binary_expression
;
keyword_expression:
binary_object_description keyword_binary_object_description_list
{ $$ = makeKeywordExpr($1, $2); }
;
keyword_binary_object_description_list:
keyword binary_object_description
{ $$ = makeKeywordList($1, $2); }
| keyword_binary_object_description_list keyword
binary_object_description { addNode($1, makeKeywordList($2, $3));
$$ = $1; }
;
cascaded_message_expression:
message_expression semi_message_list
{ $$ = makeCascadedMessage($1, $2); }
;
semi_message_list:
SEMICOLON message_elt { $$ = makeMessageList($2); }
| semi_message_list SEMICOLON message_elt
{ addNode($1, makeMessageList($3));
$$ = $1; }
;
message_elt:
unary_selector { $$ = makeUnaryExpr(nil, $1); }
| binary_selector unary_object_description
{ $$ = makeBinaryExpr(nil, $1, $2); }
| keyword_binary_object_description_list
{ $$ = makeKeywordExpr(nil, $1); }
;
%%
/*
ADDITIONAL C CODE
*/